package manager.http;



import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpHeaderValues;
import io.netty.handler.codec.http.HttpHeaders.Names;
import io.netty.handler.codec.http.HttpHeaders.Values;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.handler.codec.http.multipart.Attribute;
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
import io.netty.handler.codec.http.multipart.InterfaceHttpData;
import io.netty.util.CharsetUtil;
import manager.connection.ClientConnectionManager;
import manager.connection.type.ConnectionInfo;
import manager.pay.GetPayResult;
import manager.pay.state.ConsumptionType;
import manager.pay.type.EndTimeInfo;
import manager.pay.type.ntfPlayerPayStatusInfo;
import manager.songlist.Songlist;
import manager.songlist.SonglistControl;
import net.socket.server.notification.GameServerWechatLoginNTF;
import net.socket.server.protocal.PROTOID;
import service.message.QRCodeEvent;
import service.message.WeixinUserInfo;
import service.message.XCXWeChatUserInfo;
import util.MyFactory;
import util.ResultTypeList;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.log4j.Logger;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.alibaba.dubbo.config.support.Parameter;
import com.fasterxml.jackson.databind.ObjectMapper;

import advice.ExceptionManager;
import database.DBService;
import database.dao.UserInfoDao;
import database.pojo.MachineInfo;
import database.pojo.UserInfo;
import database.pojo.UserRechargeInfo;

/**
 * 
* Title: NettyServerHandler
* Description: 处理支付回调
* @version 0.0.1  
* @author zk
* @date 2018-4-17
 */
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
	private static Logger logger = Logger.getLogger(ExceptionManager.class);
	
	@SuppressWarnings("deprecation")
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

		if(! (msg instanceof FullHttpRequest)){
			return;
	 	}
		
		FullHttpRequest httpRequest = (FullHttpRequest)msg;
		ClientConnectionManager ccm = new  ClientConnectionManager();
		try{
			String path=httpRequest.uri();
			
			Map<String, String> result = new HashMap<String, String>();
			if (httpRequest.method() == HttpMethod.POST) {
				result = parseOutTradeNoOfPay(httpRequest);
			
				if ( path.contains("pay")) {
					
			    	ntfPlayerPayStatusInfo rsp = new ntfPlayerPayStatusInfo();
			    	rsp.setConsumptionType(ConsumptionType.BUYPACKET);
			    	
			    	int mid = Integer.parseInt(result.get("mid"));
			    	int AddTime = Integer.parseInt(result.get("time"));
			    	String openid = String.format("%s",result.get("openid"));
			    	long EndTime = 0;
			    	//查询剩余时间
			    	System.out.println(result);
			    	System.out.println("1____________");
			    	System.out.println(openid);
			    	
			    	UserInfo userInfo = MyFactory.context.getBean("DBService",DBService.class).selectUserInfoByOpenId(openid);
			    	MachineInfo minfo =  MyFactory.context.getBean("DBService",DBService.class).selectMachineInfoById(mid);
			    	
			    	if( AddTime>0 && minfo.getEndTime() < System.currentTimeMillis()) {
			    		EndTime = System.currentTimeMillis()+1000*60*AddTime;	
			    	}
			    	if (AddTime >0 && minfo.getEndTime() >= System.currentTimeMillis()) {
			    		EndTime = minfo.getEndTime()+1000*60*AddTime;	
			    	}
			    	MyFactory.context.getBean("DBService",DBService.class).updateEndtime(mid, EndTime);    	
			   		rsp.setEndTime(EndTime); 
			   		rsp.setUserInfo(userInfo);
			    	ccm.sendResponse(PROTOID.NTF_PLAYER_PAY_STATUS, mid , rsp);
			    	
			    	//计时器通知客户端时间到了
			    	EndTimeInfo einfo = new EndTimeInfo();
					einfo.setEndTime(EndTime);
					einfo.setMid(mid);
					Boolean iscontails = MyFactory.context.getBean("GetPayResult", GetPayResult.class).containsMap(Integer.toString(mid));
					if (!iscontails){
						System.out.println("add EndTimeInfo___________");
						MyFactory.context.getBean("GetPayResult", GetPayResult.class).putMap(Integer.toString(mid), einfo);
					}else {
						EndTimeInfo e = MyFactory.context.getBean("GetPayResult", GetPayResult.class).getMap(Integer.toString(mid));
						e.setEndTime(EndTime);
						System.out.println("update EndTimeInfo_______");
					}
			    	
			    	return ;
				}
				if (path.contains("control")){
					System.out.println("control______start");
					SonglistControl rsp1 = new SonglistControl();
					rsp1.setControlType(Integer.parseInt(result.get("ControlType")));
					ccm.sendResponse(PROTOID.NOTIFY_CONTROL_RSP, Integer.parseInt(result.get("mid")) , rsp1); // 通知控制指令
				
					return ;
				}
				if (path.contains("songlist")){
					System.out.println("songlist______1");
					Songlist rsp2 = new Songlist();
					rsp2.setSonglist(result.get("songlist"));
					rsp2.setLength(Integer.parseInt(result.get("length")));
					ccm.sendResponse(PROTOID.NOTIFY_UPDATE_SONGLIST_REQ, Integer.parseInt(result.get("mid")) ,rsp2); // 通知歌单更新
					return ;
				}
				
				if (path.contains("machineStatus")){
					int mid = Integer.parseInt(result.get("mid"));
					ConnectionInfo connect = MyFactory.context.getBean("ClientConnectionManager",ClientConnectionManager.class).getConnectionInfo(mid);
					if (mid == connect.getMachineId()) {
						return ;
					}
				}
				if(path.contains("login")) {
					ObjectMapper mapper = new ObjectMapper();
					String rawData = result.get("rawData");
					int mid = Integer.parseInt(result.get("mid"));
					XCXWeChatUserInfo wUserInfo = mapper.readValue(rawData, XCXWeChatUserInfo.class);
					System.out.println(wUserInfo.getNickName());
					GameServerWechatLoginNTF ntf = new GameServerWechatLoginNTF();
					ntf.setPlayerInfo(wUserInfo);
					
					ChannelFuture cf = ccm.sendResponse(PROTOID.GAME_SVR_PLAYER_LOGIN_NTF, mid,ntf);
					return ;
				}
				
				
				
				
			}
			else {
				System.out.println("NO KWON HTTP REQ");
				logger.info("NO KWON HTTP REQ");
				return ;
			}
		}catch(Exception e){
			System.out.println("处理请求失败!");
			e.printStackTrace();
		}finally{
			//释放请求
			httpRequest.release();
		}
	}
	
	private void send(ChannelHandlerContext ctx, String context,HttpResponseStatus status,String path) {
		FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, Unpooled.copiedBuffer(context, CharsetUtil.UTF_8));
		response.headers().set(HttpHeaderNames.CONTENT_TYPE, path);
		ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
	}
 
	/**
     * 解析请求参数
     * @return 包含所有请求参数的键值对, 如果没有参数, 则返回空
     *
     * @throws BaseCheckedException
     * @throws IOException
	 * @throws IllegalAccessException 
	 * @throws IllegalArgumentException 
     */
    public Map<String,String> parseOutTradeNoOfPay(FullHttpRequest fullReq) throws IOException, IllegalArgumentException, IllegalAccessException  {
        HttpMethod method = fullReq.method();

       int sigin = ResultTypeList.UNKNOWN_FAIL;
       Map<String, String> dateMap = new HashMap<>();
       
            // 是POST请求
    	    System.out.println("get http post ___________");
            HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(fullReq);
            decoder.offer(fullReq);

            List<InterfaceHttpData> parmList = decoder.getBodyHttpDatas();
            for (InterfaceHttpData parm : parmList) {
            	
                Attribute data = (Attribute) parm;            
                sigin =ResultTypeList.SUCCESS;   
                dateMap.put(data.getName(), data.getValue());
                //System.out.println("data.getName:"+data.getName());
               //System.out.println("data.getValue---------:"+data.getValue());                                            	
            }
       
            if (sigin == ResultTypeList.SUCCESS) {
            	return dateMap;
       		} else {
       			return null;
       		} 
    }
    
    private String getBody(FullHttpRequest request){
    	HttpMethod method = request.method();
    	if (HttpMethod.POST == method) {
    		ByteBuf buf = request.content();
    		return buf.toString(CharsetUtil.UTF_8);
    	  }else {
    		//System.out.println("not post method");
    		  logger.info("not post method");
			return null;
		}
    	
		
	}
      
       /**
        * XML格式字符串转换为Map
        *
        * @param strXML XML字符串
        * @return XML数据转换后的Map
        * @throws Exception
        */
       public static Map<String, String> xmlToMap(String strXML) throws Exception {
           Map<String, String> data = new HashMap<String, String>();
           DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
           DocumentBuilder documentBuilder= documentBuilderFactory.newDocumentBuilder();
           InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
           org.w3c.dom.Document doc = documentBuilder.parse(stream);
           doc.getDocumentElement().normalize();
           NodeList nodeList = doc.getDocumentElement().getChildNodes();
           for (int idx=0; idx<nodeList.getLength(); ++idx) {
               Node node = nodeList.item(idx);
               if (node.getNodeType() == Node.ELEMENT_NODE) {
                   org.w3c.dom.Element element = (org.w3c.dom.Element) node;
                   data.put(element.getNodeName(), element.getTextContent());
                   //System.out.println("element.getNodeName():"+element.getNodeName()+": element.getTextContent()"+element.getTextContent());
               }
           }
           try {
               stream.close();
           }
           catch (Exception ex) {

           }
           return data;
       }
	
	
	
	
}
